// Copyright (c) Huawei Technologies Co., Ltd. 2025. All rights reserved.
// This source file is part of the Cangjie project, licensed under Apache-2.0
// with Runtime Library Exception.
//
// See https://cangjie-lang.cn/pages/LICENSE for license information.

#if defined(PLATFORM_WINDOWS)
#include <windows.h>
#endif

#include <cstdlib>

#include "Path.h"

#include "Platform/EnvironmentVariable.h"

namespace Platform {

#if defined(PLATFORM_WINDOWS)
const std::string EnvironmentVariable::Separator = ";";
#elif defined(PLATFORM_LINUX) || defined(PLATFORM_MACOS)
const std::string EnvironmentVariable::Separator = ":";
#endif

std::string EnvironmentVariable::ExpandValue() const
{
#if defined(PLATFORM_WINDOWS)
    return value + Separator + '%' + name + '%';
#elif defined(PLATFORM_LINUX) || defined(PLATFORM_MACOS)
    return value + Separator + "${" + name + "}";
#endif
}

std::string EnvironmentVariable::GenerateCommand() const
{
    if (expand) {
        return GenerateCommandExpand();
    } else {
        return GenerateCommandUnExpand();
    }
}

std::string EnvironmentVariable::GenerateCommandExpand() const
{
#if defined(PLATFORM_WINDOWS)
    return "set \"" + name + "=" + ExpandValue() + "\"";
#elif defined(PLATFORM_LINUX) || defined(PLATFORM_MACOS)
    return "export " + name + '=' + ExpandValue();
#endif
}

std::string EnvironmentVariable::GenerateCommandUnExpand() const
{
#if defined(PLATFORM_WINDOWS)
    return "set \"" + name + "=" + value + "\"";
#elif defined(PLATFORM_LINUX) || defined(PLATFORM_MACOS)
    return "export " + name + '=' + value;
#endif
}

EnvironmentVariable::EnvironmentVariable(std::string name, std::string value)
    : name(std::move(name)), value(std::move(value)), expand(false)
{}

EnvironmentVariable::EnvironmentVariable(std::string name, std::string value, const bool expand)
    : name(std::move(name)), value(std::move(value)), expand(expand)
{}

std::unique_ptr<Path> EnvironmentVariable::GetPath(const std::string &name)
{
    const auto value = GetValue(name);
    if (value == nullptr) {
        return nullptr;
    }
    return std::make_unique<Path>(*value);
}

std::unique_ptr<std::string> EnvironmentVariable::GetValue(const std::string &name)
{
#if defined(PLATFORM_WINDOWS)
    char buffer[1024] = { 0 };
    DWORD len = GetEnvironmentVariableA(name.c_str(), buffer, sizeof buffer);
    if (len == 0 || len >= sizeof buffer) {
        return nullptr;
    }
    return std::make_unique<std::string>(buffer, len);
#else
    const char *val = std::getenv(name.c_str());
    if (val == nullptr) {
        return nullptr;
    }
    return std::make_unique<std::string>(val);
#endif
}

std::unique_ptr<EnvironmentVariable> EnvironmentVariable::Get(const std::string &name)
{
    const auto value = GetValue(name);
    if (value == nullptr) {
        return nullptr;
    }
    return std::make_unique<EnvironmentVariable>(name, *value);
}

} // namespace Platform
